package com.xiaoyu.base.net.request;

import com.xiaoyu.net.request.RequestWithJsonDataReturn;
import com.xiaoyu.base.event.BaseEvent;
import com.xiaoyu.base.event.BaseJsonEvent;
import com.xiaoyu.base.event.ErrorMessageEvent;
import com.xiaoyu.base.event.NoReceiverJsonEvent;

import java.lang.reflect.Constructor;

import in.srain.cube.request.FailData;
import in.srain.cube.request.JsonData;
import in.srain.cube.util.CLog;

public class JsonEventRequest<T> extends RequestWithJsonDataReturn<T> {

    private static final String TAG = "JsonEventRequest";
    private Class<? extends BaseJsonEvent> mEventClass;
    private Object mRequestTag = null;

    public JsonEventRequest(Object requestTag, Class<? extends BaseJsonEvent> eventClass) {
        if (requestTag == null) {
            throw new RuntimeException("The request tag should not be null.");
        }
        mRequestTag = requestTag;
        mEventClass = eventClass;
    }

    @Override
    public T processOriginDataFromServer(JsonData originData) {
        return createEvent(originData.optJson("data"));
    }

    private T createEvent(JsonData data) {

        final Object[] instanceObjects = new Object[]{mRequestTag, data};
        final Class[] parameterTypes = new Class[]{Object.class, data.getClass()};
        instanceObjects[0] = mRequestTag;
        instanceObjects[1] = data;
        Constructor<?> constructor = null;
        try {
            constructor = mEventClass.getDeclaredConstructor(parameterTypes);
            BaseJsonEvent event = (BaseJsonEvent) constructor.newInstance(instanceObjects);
            return (T) event;
        } catch (Exception e) {
            // OK to catch Exception here
            CLog.e(TAG, "error when create event class: %s", mEventClass);
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void onRequestFail(Object requestTag, FailData failData) {
        super.onRequestFail(mRequestTag, failData);
        new ErrorMessageEvent(mRequestTag, failData.getException().getMessage()).post();
        if (mPostEventWhenFail) {
            Object object = createEvent(JsonData.create(null));
            if (object == null || !(object instanceof BaseEvent)) {
                return;
            }
            BaseEvent event = (BaseEvent) object;
            event.fail(failData).post();
        }
    }

    @Override
    public void onRequestSuccess(T event) {
        super.onRequestSuccess(event);
        if (event == null) {
            return;
        }
        if (event instanceof NoReceiverJsonEvent) {
            return;
        }
        if (event instanceof BaseEvent) {
            ((BaseEvent) event).post();
        }
    }
}
